home *** CD-ROM | disk | FTP | other *** search
/ Micromanía 92 / CDMM92_1.ISO / SOF 2 SDK / sof2sdk-101.msi / _92D6AC311BB48EBA344BBABC89DA6AB0 / _F68823F860294593A4FCF5CC590FD648 < prev    next >
Encoding:
Text File  |  2002-06-05  |  13.4 KB  |  800 lines

  1. // Copyright (C) 2001-2002 Raven Software.
  2. //
  3. // ai_util.c
  4.  
  5. #include "g_local.h"
  6. #include "q_shared.h"
  7. #include "botlib.h"
  8. #include "ai_main.h"
  9.  
  10. #ifdef BOT_ZMALLOC
  11. #define MAX_BALLOC 8192
  12.  
  13. void *BAllocList[MAX_BALLOC];
  14. #endif
  15.  
  16. char gBotChatBuffer[MAX_CLIENTS][MAX_CHAT_BUFFER_SIZE];
  17. //A total of 4194304 bytes. Not very nice at all, but we really
  18. //want to have at least 65k for the total chat buffer just in
  19. //case and we have no method of dynamic allocation here.
  20.  
  21. void *B_TempAlloc(int size)
  22. {
  23.     return trap_VM_LocalTempAlloc(size);
  24. }
  25.  
  26. void B_TempFree(int size)
  27. {
  28.     trap_VM_LocalTempFree(size);
  29. }
  30.  
  31.  
  32. void *B_Alloc(int size)
  33. {
  34. #ifdef BOT_ZMALLOC
  35.     void *ptr = NULL;
  36.     int i = 0;
  37.  
  38. #ifdef BOTMEMTRACK
  39.     int free = 0;
  40.     int used = 0;
  41.  
  42.     while (i < MAX_BALLOC)
  43.     {
  44.         if (!BAllocList[i])
  45.         {
  46.             free++;
  47.         }
  48.         else
  49.         {
  50.             used++;
  51.         }
  52.  
  53.         i++;
  54.     }
  55.  
  56.     Com_Printf("Allocations used: %i\nFree allocation slots: %i\n", used, free);
  57.  
  58.     i = 0;
  59. #endif
  60.  
  61.     ptr = trap_BotGetMemoryGame(size);
  62.  
  63.     while (i < MAX_BALLOC)
  64.     {
  65.         if (!BAllocList[i])
  66.         {
  67.             BAllocList[i] = ptr;
  68.             break;
  69.         }
  70.         i++;
  71.     }
  72.  
  73.     if (i == MAX_BALLOC)
  74.     {
  75.         //If this happens we'll have to rely on this chunk being freed manually with B_Free, which it hopefully will be
  76. #ifdef DEBUG
  77.         Com_Printf("WARNING: MAXIMUM B_ALLOC ALLOCATIONS EXCEEDED\n");
  78. #endif
  79.     }
  80.  
  81.     return ptr;
  82. #else
  83.  
  84.     return trap_VM_LocalAlloc(size);
  85.  
  86. #endif
  87. }
  88.  
  89. void B_Free(void *ptr)
  90. {
  91. #ifdef BOT_ZMALLOC
  92.     int i = 0;
  93.  
  94. #ifdef BOTMEMTRACK
  95.     int free = 0;
  96.     int used = 0;
  97.  
  98.     while (i < MAX_BALLOC)
  99.     {
  100.         if (!BAllocList[i])
  101.         {
  102.             free++;
  103.         }
  104.         else
  105.         {
  106.             used++;
  107.         }
  108.  
  109.         i++;
  110.     }
  111.  
  112.     Com_Printf("Allocations used: %i\nFree allocation slots: %i\n", used, free);
  113.  
  114.     i = 0;
  115. #endif
  116.  
  117.     while (i < MAX_BALLOC)
  118.     {
  119.         if (BAllocList[i] == ptr)
  120.         {
  121.             BAllocList[i] = NULL;
  122.             break;
  123.         }
  124.  
  125.         i++;
  126.     }
  127.  
  128.     if (i == MAX_BALLOC)
  129.     {
  130.         //Likely because the limit was exceeded and we're now freeing the chunk manually as we hoped would happen
  131. #ifdef DEBUG
  132.         Com_Printf("WARNING: Freeing allocation which is not in the allocation structure\n");
  133. #endif
  134.     }
  135.  
  136.     trap_BotFreeMemoryGame(ptr);
  137. #endif
  138. }
  139.  
  140. void B_InitAlloc(void)
  141. {
  142. #ifdef BOT_ZMALLOC
  143.     memset(BAllocList, 0, sizeof(BAllocList));
  144. #endif
  145.  
  146.     memset(gWPArray, 0, sizeof(gWPArray));
  147. }
  148.  
  149. void B_CleanupAlloc(void)
  150. {
  151. #ifdef BOT_ZMALLOC
  152.     int i = 0;
  153.  
  154.     while (i < MAX_BALLOC)
  155.     {
  156.         if (BAllocList[i])
  157.         {
  158.             trap_BotFreeMemoryGame(BAllocList[i]);
  159.             BAllocList[i] = NULL;
  160.         }
  161.  
  162.         i++;
  163.     }
  164. #endif
  165. }
  166.  
  167. int GetValueGroup(char *buf, char *group, char *outbuf)
  168. {
  169.     char *place, *placesecond;
  170.     int iplace;
  171.     int failure;
  172.     int i;
  173.     int startpoint, startletter;
  174.     int subg = 0;
  175.  
  176.     i = 0;
  177.  
  178.     iplace = 0;
  179.  
  180.     place = strstr(buf, group);
  181.  
  182.     if (!place)
  183.     {
  184.         return 0;
  185.     }
  186.  
  187.     startpoint = place - buf + strlen(group) + 1;
  188.     startletter = (place - buf) - 1;
  189.  
  190.     failure = 0;
  191.  
  192.     while (buf[startpoint+1] != '{' || buf[startletter] != '\n')
  193.     {
  194.         placesecond = strstr(place+1, group);
  195.  
  196.         if (placesecond)
  197.         {
  198.             startpoint += (placesecond - place);
  199.             startletter += (placesecond - place);
  200.             place = placesecond;
  201.         }
  202.         else
  203.         {
  204.             failure = 1;
  205.             break;
  206.         }
  207.     }
  208.  
  209.     if (failure)
  210.     {
  211.         return 0;
  212.     }
  213.  
  214.     //we have found the proper group name if we made it here, so find the opening brace and read into the outbuf
  215.     //until hitting the end brace
  216.  
  217.     while (buf[startpoint] != '{')
  218.     {
  219.         startpoint++;
  220.     }
  221.  
  222.     startpoint++;
  223.  
  224.     while (buf[startpoint] != '}' || subg)
  225.     {
  226.         if (buf[startpoint] == '{')
  227.         {
  228.             subg++;
  229.         }
  230.         else if (buf[startpoint] == '}')
  231.         {
  232.             subg--;
  233.         }
  234.         outbuf[i] = buf[startpoint];
  235.         i++;
  236.         startpoint++;
  237.     }
  238.     outbuf[i] = '\0';
  239.  
  240.     return 1;
  241. }
  242.  
  243. int GetPairedValue(char *buf, char *key, char *outbuf)
  244. {
  245.     char *place, *placesecond;
  246.     int startpoint, startletter;
  247.     int i, found;
  248.  
  249.     if (!buf || !key || !outbuf)
  250.     {
  251.         return 0;
  252.     }
  253.  
  254.     i = 0;
  255.  
  256.     while (buf[i] && buf[i] != '\0')
  257.     {
  258.         if (buf[i] == '/')
  259.         {
  260.             if (buf[i+1] && buf[i+1] != '\0' && buf[i+1] == '/')
  261.             {
  262.                 while (buf[i] != '\n')
  263.                 {
  264.                     buf[i] = '/';
  265.                     i++;
  266.                 }
  267.             }
  268.         }
  269.         i++;
  270.     }
  271.  
  272.     place = strstr(buf, key);
  273.  
  274.     if (!place)
  275.     {
  276.         return 0;
  277.     }
  278.     //tab == 9
  279.     startpoint = place - buf + strlen(key);
  280.     startletter = (place - buf) - 1;
  281.  
  282.     found = 0;
  283.  
  284.     while (!found)
  285.     {
  286.         if (startletter == 0 || !buf[startletter] || buf[startletter] == '\0' || buf[startletter] == 9 || buf[startletter] == ' ' || buf[startletter] == '\n')
  287.         {
  288.             if (buf[startpoint] == '\0' || buf[startpoint] == 9 || buf[startpoint] == ' ' || buf[startpoint] == '\n')
  289.             {
  290.                 found = 1;
  291.                 break;
  292.             }
  293.         }
  294.  
  295.         placesecond = strstr(place+1, key);
  296.  
  297.         if (placesecond)
  298.         {
  299.             startpoint += placesecond - place;
  300.             startletter += placesecond - place;
  301.             place = placesecond;
  302.         }
  303.         else
  304.         {
  305.             place = NULL;
  306.             break;
  307.         }
  308.  
  309.     }
  310.  
  311.     if (!found || !place || !buf[startpoint] || buf[startpoint] == '\0')
  312.     {
  313.         return 0;
  314.     }
  315.  
  316.     while (buf[startpoint] == ' ' || buf[startpoint] == 9 || buf[startpoint] == '\n')
  317.     {
  318.         startpoint++;
  319.     }
  320.  
  321.     i = 0;
  322.  
  323.     while (buf[startpoint] && buf[startpoint] != '\0' && buf[startpoint] != '\n')
  324.     {
  325.         outbuf[i] = buf[startpoint];
  326.         i++;
  327.         startpoint++;
  328.     }
  329.  
  330.     outbuf[i] = '\0';
  331.  
  332.     return 1;
  333. }
  334.  
  335. int BotDoChat(bot_state_t *bs, char *section, int always)
  336. {
  337.     char *chatgroup;
  338.     int rVal;
  339.     int inc_1;
  340.     int inc_2;
  341.     int inc_n;
  342.     int lines;
  343.     int checkedline;
  344.     int getthisline;
  345.     gentity_t *cobject;
  346.  
  347.     if (!bs->canChat)
  348.     {
  349.         return 0;
  350.     }
  351.  
  352.     if (bs->doChat)
  353.     { //already have a chat scheduled
  354.         return 0;
  355.     }
  356.  
  357.     if (Q_irand(1, 10) > bs->chatFrequency && !always)
  358.     {
  359.         return 0;
  360.     }
  361.  
  362.     bs->chatTeam = 0;
  363.  
  364.     chatgroup = (char *)B_TempAlloc(MAX_CHAT_BUFFER_SIZE);
  365.  
  366.     rVal = GetValueGroup(gBotChatBuffer[bs->client], section, chatgroup);
  367.  
  368.     if (!rVal) //the bot has no group defined for the specified chat event
  369.     {
  370.         B_TempFree(MAX_CHAT_BUFFER_SIZE); //chatgroup
  371.         return 0;
  372.     }
  373.  
  374.     inc_1 = 0;
  375.     inc_2 = 2;
  376.  
  377.     while (chatgroup[inc_2] && chatgroup[inc_2] != '\0')
  378.     {
  379.         if (chatgroup[inc_2] != 13 && chatgroup[inc_2] != 9)
  380.         {
  381.             chatgroup[inc_1] = chatgroup[inc_2];
  382.             inc_1++;
  383.         }
  384.         inc_2++;
  385.     }
  386.     chatgroup[inc_1] = '\0';
  387.  
  388.     inc_1 = 0;
  389.  
  390.     lines = 0;
  391.  
  392.     while (chatgroup[inc_1] && chatgroup[inc_1] != '\0')
  393.     {
  394.         if (chatgroup[inc_1] == '\n')
  395.         {
  396.             lines++;
  397.         }
  398.         inc_1++;
  399.     }
  400.  
  401.     if (!lines)
  402.     {
  403.         B_TempFree(MAX_CHAT_BUFFER_SIZE); //chatgroup
  404.         return 0;
  405.     }
  406.  
  407.     getthisline = Q_irand(0, (lines+1));
  408.  
  409.     if (getthisline < 1)
  410.     {
  411.         getthisline = 1;
  412.     }
  413.     if (getthisline > lines)
  414.     {
  415.         getthisline = lines;
  416.     }
  417.  
  418.     checkedline = 1;
  419.  
  420.     inc_1 = 0;
  421.  
  422.     while (checkedline != getthisline)
  423.     {
  424.         if (chatgroup[inc_1] && chatgroup[inc_1] != '\0')
  425.         {
  426.             if (chatgroup[inc_1] == '\n')
  427.             {
  428.                 inc_1++;
  429.                 checkedline++;
  430.             }
  431.         }
  432.  
  433.         if (checkedline == getthisline)
  434.         {
  435.             break;
  436.         }
  437.  
  438.         inc_1++;
  439.     }
  440.  
  441.     //we're at the starting position of the desired line here
  442.     inc_2 = 0;
  443.  
  444.     while (chatgroup[inc_1] != '\n')
  445.     {
  446.         chatgroup[inc_2] = chatgroup[inc_1];
  447.         inc_2++;
  448.         inc_1++;
  449.     }
  450.     chatgroup[inc_2] = '\0';
  451.  
  452.     //trap_EA_Say(bs->client, chatgroup);
  453.     inc_1 = 0;
  454.     inc_2 = 0;
  455.  
  456.     if (strlen(chatgroup) > MAX_CHAT_LINE_SIZE)
  457.     {
  458.         B_TempFree(MAX_CHAT_BUFFER_SIZE); //chatgroup
  459.         return 0;
  460.     }
  461.  
  462.     while (chatgroup[inc_1])
  463.     {
  464.         if (chatgroup[inc_1] == '%' && chatgroup[inc_1+1] != '%')
  465.         {
  466.             inc_1++;
  467.  
  468.             if (chatgroup[inc_1] == 's' && bs->chatObject)
  469.             {
  470.                 cobject = bs->chatObject;
  471.             }
  472.             else if (chatgroup[inc_1] == 'a' && bs->chatAltObject)
  473.             {
  474.                 cobject = bs->chatAltObject;
  475.             }
  476.             else
  477.             {
  478.                 cobject = NULL;
  479.             }
  480.  
  481.             if (cobject && cobject->client)
  482.             {
  483.                 inc_n = 0;
  484.  
  485.                 while (cobject->client->pers.netname[inc_n])
  486.                 {
  487.                     bs->currentChat[inc_2] = cobject->client->pers.netname[inc_n];
  488.                     inc_2++;
  489.                     inc_n++;
  490.                 }
  491.                 inc_2--; //to make up for the auto-increment below
  492.             }
  493.         }
  494.         else
  495.         {
  496.             bs->currentChat[inc_2] = chatgroup[inc_1];
  497.         }
  498.         inc_2++;
  499.         inc_1++;
  500.     }
  501.     bs->currentChat[inc_2] = '\0';
  502.  
  503.     if (strcmp(section, "GeneralGreetings") == 0)
  504.     {
  505.         bs->doChat = 2;
  506.     }
  507.     else
  508.     {
  509.         bs->doChat = 1;
  510.     }
  511.     bs->chatTime_stored = (strlen(bs->currentChat)*45)+Q_irand(1300, 1500);
  512.     bs->chatTime = level.time + bs->chatTime_stored;
  513.  
  514.     B_TempFree(MAX_CHAT_BUFFER_SIZE); //chatgroup
  515.  
  516.     return 1;
  517. }
  518.  
  519. void ParseEmotionalAttachments(bot_state_t *bs, char *buf)
  520. {
  521.     int i = 0;
  522.     int i_c = 0;
  523.     char tbuf[16];
  524.  
  525.     while (buf[i] && buf[i] != '}')
  526.     {
  527.         while (buf[i] == ' ' || buf[i] == '{' || buf[i] == 9 || buf[i] == 13 || buf[i] == '\n')
  528.         {
  529.             i++;
  530.         }
  531.  
  532.         if (buf[i] && buf[i] != '}')
  533.         {
  534.             i_c = 0;
  535.             while (buf[i] != '{' && buf[i] != 9 && buf[i] != 13 && buf[i] != '\n')
  536.             {
  537.                 bs->loved[bs->lovednum].name[i_c] = buf[i];
  538.                 i_c++;
  539.                 i++;
  540.             }
  541.             bs->loved[bs->lovednum].name[i_c] = '\0';
  542.  
  543.             while (buf[i] == ' ' || buf[i] == '{' || buf[i] == 9 || buf[i] == 13 || buf[i] == '\n')
  544.             {
  545.                 i++;
  546.             }
  547.  
  548.             i_c = 0;
  549.  
  550.             while (buf[i] != '{' && buf[i] != 9 && buf[i] != 13 && buf[i] != '\n')
  551.             {
  552.                 tbuf[i_c] = buf[i];
  553.                 i_c++;
  554.                 i++;
  555.             }
  556.             tbuf[i_c] = '\0';
  557.  
  558.             bs->loved[bs->lovednum].level = atoi(tbuf);
  559.  
  560.             bs->lovednum++;
  561.         }
  562.         else
  563.         {
  564.             break;
  565.         }
  566.  
  567.         if (bs->lovednum >= MAX_LOVED_ONES)
  568.         {
  569.             return;
  570.         }
  571.  
  572.         i++;
  573.     }
  574. }
  575.  
  576. int ReadChatGroups(bot_state_t *bs, char *buf)
  577. {
  578.     char *cgroupbegin;
  579.     int cgbplace;
  580.     int i;
  581.  
  582.     cgroupbegin = strstr(buf, "BEGIN_CHAT_GROUPS");
  583.  
  584.     if (!cgroupbegin)
  585.     {
  586.         return 0;
  587.     }
  588.  
  589.     if (strlen(cgroupbegin) >= MAX_CHAT_BUFFER_SIZE)
  590.     {
  591.         Com_Printf(S_COLOR_RED "Error: Personality chat section exceeds max size\n");
  592.         return 0;
  593.     }
  594.  
  595.     cgbplace = cgroupbegin - buf+1;
  596.  
  597.     while (buf[cgbplace] != '\n')
  598.     {
  599.         cgbplace++;
  600.     }
  601.  
  602.     i = 0;
  603.  
  604.     while (buf[cgbplace] && buf[cgbplace] != '\0')
  605.     {
  606.         gBotChatBuffer[bs->client][i] = buf[cgbplace];
  607.         i++;
  608.         cgbplace++;
  609.     }
  610.  
  611.     gBotChatBuffer[bs->client][i] = '\0';
  612.  
  613.     return 1;
  614. }
  615.  
  616. char personalityBuffer[131072];
  617.  
  618. void BotUtilizePersonality(bot_state_t *bs)
  619. {
  620.     fileHandle_t f;
  621.     int len, rlen;
  622.     int failed;
  623.     int i;
  624.     char *readbuf, *group;
  625.  
  626.     len = trap_FS_FOpenFile(bs->settings.personalityfile, &f, FS_READ);
  627.  
  628.     failed = 0;
  629.  
  630.     if (!f)
  631.     {
  632.         Com_Printf(S_COLOR_RED "Error: Specified personality not found\n");
  633.         return;
  634.     }
  635.  
  636.     if (len >= 131072)
  637.     {
  638.         Com_Printf(S_COLOR_RED "Personality file exceeds maximum length\n");
  639.         return;
  640.     }
  641.  
  642.     trap_FS_Read(personalityBuffer, len, f);
  643.  
  644.     rlen = len;
  645.  
  646.     while (len < 131072)
  647.     { //kill all characters after the file length, since sometimes FS_Read doesn't do that entirely (or so it seems)
  648.         personalityBuffer[len] = '\0';
  649.         len++;
  650.     }
  651.  
  652.     len = rlen;
  653.  
  654.     readbuf = (char *)trap_VM_LocalTempAlloc(1024);
  655.     group = (char *)trap_VM_LocalTempAlloc(65536);
  656.  
  657.     if (!GetValueGroup(personalityBuffer, "GeneralBotInfo", group))
  658.     {
  659.         Com_Printf(S_COLOR_RED "Personality file contains no GeneralBotInfo group\n");
  660.         failed = 1; //set failed so we know to set everything to default values
  661.     }
  662.  
  663.     if (!failed && GetPairedValue(group, "reflex", readbuf))
  664.     {
  665.         bs->skills.reflex = atoi(readbuf);
  666.     }
  667.     else
  668.     {
  669.         bs->skills.reflex = 100; //default
  670.     }
  671.  
  672.     if (!failed && GetPairedValue(group, "accuracy", readbuf))
  673.     {
  674.         bs->skills.accuracy = atof(readbuf);
  675.     }
  676.     else
  677.     {
  678.         bs->skills.accuracy = 10; //default
  679.     }
  680.  
  681.     if (!failed && GetPairedValue(group, "turnspeed", readbuf))
  682.     {
  683.         bs->skills.turnspeed = atof(readbuf);
  684.     }
  685.     else
  686.     {
  687.         bs->skills.turnspeed = 0.01f; //default
  688.     }
  689.  
  690.     if (!failed && GetPairedValue(group, "turnspeed_combat", readbuf))
  691.     {
  692.         bs->skills.turnspeed_combat = atof(readbuf);
  693.     }
  694.     else
  695.     {
  696.         bs->skills.turnspeed_combat = 0.05f; //default
  697.     }
  698.  
  699.     if (!failed && GetPairedValue(group, "maxturn", readbuf))
  700.     {
  701.         bs->skills.maxturn = atof(readbuf);
  702.     }
  703.     else
  704.     {
  705.         bs->skills.maxturn = 360; //default
  706.     }
  707.  
  708.     if (!failed && GetPairedValue(group, "perfectaim", readbuf))
  709.     {
  710.         bs->skills.perfectaim = atoi(readbuf);
  711.     }
  712.     else
  713.     {
  714.         bs->skills.perfectaim = 0; //default
  715.     }
  716.  
  717.     if (!failed && GetPairedValue(group, "chatability", readbuf))
  718.     {
  719.         bs->canChat = atoi(readbuf);
  720.     }
  721.     else
  722.     {
  723.         bs->canChat = 0; //default
  724.     }
  725.  
  726.     if (!failed && GetPairedValue(group, "chatfrequency", readbuf))
  727.     {
  728.         bs->chatFrequency = atoi(readbuf);
  729.     }
  730.     else
  731.     {
  732.         bs->chatFrequency = 5; //default
  733.     }
  734.  
  735.     if (!failed && GetPairedValue(group, "hatelevel", readbuf))
  736.     {
  737.         bs->loved_death_thresh = atoi(readbuf);
  738.     }
  739.     else
  740.     {
  741.         bs->loved_death_thresh = 3; //default
  742.     }
  743.  
  744.     if (!failed && GetPairedValue(group, "camper", readbuf))
  745.     {
  746.         bs->isCamper = atoi(readbuf);
  747.     }
  748.     else
  749.     {
  750.         bs->isCamper = 0; //default
  751.     }
  752.  
  753.     if (!failed && GetPairedValue(group, "meleeSpecialist", readbuf))
  754.     {
  755.         bs->meleeSpecialist = atoi(readbuf);
  756.     }
  757.     else
  758.     {
  759.         bs->meleeSpecialist = 0; //default
  760.     }
  761.  
  762.     i = 0;
  763.  
  764.     while (i < MAX_CHAT_BUFFER_SIZE)
  765.     { //clear out the chat buffer for this bot
  766.         gBotChatBuffer[bs->client][i] = '\0';
  767.         i++;
  768.     }
  769.  
  770.     if (bs->canChat)
  771.     {
  772.         if (!ReadChatGroups(bs, personalityBuffer))
  773.         {
  774.             bs->canChat = 0;
  775.         }
  776.     }
  777.  
  778.     if (GetValueGroup(personalityBuffer, "BotWeaponWeights", group))
  779.     {
  780.         for (i=0; i < WP_NUM_WEAPONS; i++)
  781.         {
  782.             if (GetPairedValue(group, bg_weaponNames[i], readbuf))
  783.             {
  784.                 bs->botWeaponWeights[i] = atoi(readbuf);
  785.             }
  786.         }
  787.     }
  788.  
  789.     bs->lovednum = 0;
  790.  
  791.     if (GetValueGroup(personalityBuffer, "EmotionalAttachments", group))
  792.     {
  793.         ParseEmotionalAttachments(bs, group);
  794.     }
  795.  
  796.     trap_VM_LocalTempFree(65536);
  797.     trap_VM_LocalTempFree(1024);
  798.     trap_FS_FCloseFile(f);
  799. }
  800.